home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-02-07 | 16.9 KB | 467 lines | [TEXT/MPS ] |
- {-------------------------------------------------------------------------------
- #
- # Apple Macintosh Developer Technical Support
- #
- # Code for the dialog utilities
- #
- # Program: ProcDoggie
- # File: UDialogUtils.inc1.p - Pascal Implementation
- #
- # by: Forrest Tanaka
- #
- # Copyright © 1988-1991 Apple Computer, Inc.
- # All rights reserved.
- #
- -------------------------------------------------------------------------------}
- {[j=20/57/1$] Pasmat Options}
- {$R-}
-
-
- (*******************************************************************************
- * Types
- *******************************************************************************)
-
- TYPE
- TextStRec = PACKED RECORD
- fontIndex: Byte; {Index into STR# rsrc of font name for text}
- statStyle: Byte; {Style of static text}
- statSize: Byte; {Point size of static text}
- statJust: SignedByte; {Justification of static text}
- END;
-
- DITLTmplRec = PACKED RECORD
- pad0: TextStRec; {Text style for static text items}
- displayRect: Rect; {Rect in which to display item in wind coords}
- itemType: Byte; {Type of item}
- dataLen: Byte; {Length of item data}
- CASE Integer OF
- 0: (itemRes: Integer);
- 1: (itemText: PACKED ARRAY [0..239] OF Char)
- END;
- DITLTmplPtr = ^DITLTmplRec;
-
- ItemRec = RECORD
- displayRect: Rect; {Display item rect in window coords}
- refCon: LongInt; {Used for anything client wants}
- dismissor: Boolean; {True if the item is a dismissor}
- CASE itemType: Integer OF {Code for item type or 0 if last item}
- 0: (itemControl: ControlHandle); {Handle to item control}
- 1: (itemText: Handle; {Handle to text of static text}
- itemTypeInfo: TypeInfoRec) {Type info for static text}
- END;
- ItemListArr = ARRAY [0..255] OF ItemRec;
- ItemListPtr = ^ItemListArr;
- ItemListHnd = ^ItemListPtr;
-
-
- {$S DialogUtils}
- (*******************************************************************************
- * Public: InstallDialogItems
- *
- * This routine is mainly a DITL-resource interpreter. After loading the DITL
- * resource with a resource ID passed in itemListNum into memory, it reads the
- * information in it to build up an array of dialog items in an ItemListArr,
- * which is defined in the TYPE section of this source file. This routine
- * allocates the item array and attaches it to the "items" field of the specified
- * DialogRecord. Once the item array is filled, the DITL is no longer needed and
- * is made purgeable.
- *
- * Currently, this routine handles push buttons and static text fields. Push
- * buttons are simply handled by calling NewControl. The resulting ControlHandle
- * is placed into the itemControl field of the ItemRec. For static text items,
- * a handle to the text is placed into itemText and the style information is
- * placed into the itemTypeInfo.
- *
- * Static text items are handled a little differently, and involves a change to
- * the DITL structure. I’ve kept the size of the DITL the same as it ever was,
- * but the four bytes that are described as a “placeholder for handle or
- * procedure pointer” on page 427 of Inside Macintosh I are now interpreted by
- * InstallDialogItems to hold font information for static text items. This font
- * information has the structure described by TextStRec which is declared in the
- * TYPE section of this source file. This is a four-byte record that holds the
- * type face, type style, type size, and justification (really alignment) of the
- * static text item. InstallDialogItems converts this into a TypeInfoRec
- * (declared in the UDialogUtils.p file) which is then placed into the item
- * array. When DrawDialogItems is called, it draws static text items using this
- * font information.
- *
- * The TextStRec consists of four bytes. The first bytes specifies the type
- * face to use for the static text. It doesn’t specify the font number because
- * font numbers for a particular type face can vary from system to system.
- * Instead, this field holds an index into a STR# resource which holds a list of
- * font names. The STR# resource must have a resource ID equal to the resource
- * ID of the DITL being read, that is, "itemListNum."
- *
- * The second byte specifies the style that the static text is meant to be drawn
- * in. It holds the same value as the Style type. The Style type is 16 bits
- * wide, so I declared this field as a Byte instead. The third byte specifies
- * the size of text to use. Of course, being a byte, it’s limited to a point
- * size of 255 points. I didn’t think that’d be much of a problem, and you can
- * always draw the text yourself if you needed something larger. The last byte
- * specifies the alignment of text in the static text item rectangle. This field
- * can have the values teFlushRight, teFlushLeft, teFlushDefault, and teCenter.
- *
- * I wanted to keep the DITL mechanism so that Rez and particularly ResEdit could
- * still be used to edit the DITL, even though the Dialog Manager isn’t being
- * used with these kinds of dialogs. Unfortunately, I had to redefine the Rez
- * DITL template so that it could take the static text font information, and
- * worse, ResEdit won’t edit DITLs that have non-zero values in the location that
- * I’m reading the font information. So, keeping the DITL isn’t any particular
- * advantage over defining a completely new structure. But, I’ll leave it this
- * ways for now. There ARE other resource editors that might not be quite so
- * quick to criticize my DITLs.
- *
- * If all the dialog items were installed correctly, then noErr is returned. If
- * any error happend, then the operating system result code is returned and the
- * dialog item list is disposed of, leaving aDialog unaffected.
- *******************************************************************************)
-
- FUNCTION InstallDialogItems (aDialog: DialogPtr;
- itemListNum: Integer): OSErr;
-
- TYPE
- IntPtr = ^Integer;
-
- VAR
- numItems: Integer; {Number of items in item list}
- itemNum: Integer; {Item number of item we’re installing}
- itemKind: Integer; {Type of the item}
- fontNumber: Integer; {Font number of static text item}
- ditlItemPtr: DITLTmplPtr; {Pointer to each item}
- ditlList: Handle; {Handle to DITL resource}
- itemList: ItemListHnd; {Handle to the item list}
- aControl: ControlHandle; {Handle to a control we’re installing}
- aString: Str255; {String used for a couple of things}
- staticText: Handle; {Handle to text for static text item}
- dataLen: Integer; {Length of item data, rounded up to even}
- doesDismiss: Boolean; {True if the item is a dismissor}
-
- PROCEDURE RecoverError (error: Integer);
-
- BEGIN
- IF ditlList <> NIL THEN
- BEGIN
- HUnlock (ditlList);
- HPurge (ditlList)
- END;
- IF itemList <> NIL THEN
- DisposeDialogItems (aDialog);
- DialogPeek(aDialog)^.items := NIL;
- InstallDialogItems := error;
- EXIT (InstallDialogItems)
- END;
-
- BEGIN
- ditlList := NIL;
- itemList := NIL;
-
- (* Grab the requested DITL resource *)
- ditlList := GetResource ('DITL', itemListNum);
- IF ditlList = NIL THEN
- IF ResError = noErr THEN
- RecoverError (resNotFound)
- ELSE
- RecoverError (ResError);
-
- (* Make sure we don’t lose it while we’re reading from it *)
- HNoPurge (ditlList);
-
- (* Allocate item list; add 1 for flag record and 1 for numItems-1 adj *)
- numItems := IntPtr(ditlList^)^;
- itemList := ItemListHnd(NewHandleMargin (SIZEOF (ItemRec) * (numItems +
- 2), kAllocApp, NOT kAllocClr));
- IF itemList = NIL THEN
- RecoverError (memFullErr);
-
- (* Fill with kNoItem items in case of error while building item list *)
- FOR itemNum := 0 TO numItems + 1 DO
- itemList^^ [itemNum].itemType := kNoItem;
-
- (* Put the item list into the dialog record *)
- DialogPeek(aDialog)^.items := Handle(itemList);
-
- (* Point at the first item in the DITL *)
- HLock (ditlList);
- ditlItemPtr := DITLTmplPtr(ORD4(ditlList^) + SIZEOF (Integer));
-
- (* For each item in DITL, install into item list *)
- FOR itemNum := 0 TO numItems DO
- BEGIN
- (* Get the type of the item *)
- itemKind := ditlItemPtr^.itemType;
-
- (* If itemDisable flag clear, item is a dismissor *)
- IF itemKind < 128 THEN
- doesDismiss := TRUE
- ELSE
- BEGIN
- doesDismiss := FALSE;
- itemKind := itemKind - 128
- END;
-
- (* Grab the item information *)
- IF itemKind = ctrlItem + btnCtrl THEN
- BEGIN
- (* Copy control’s title to controlTitle *)
- BlockMove (@ditlItemPtr^.dataLen, @aString, ditlItemPtr^.
- dataLen + 1);
-
- (* Create the new control *)
- aControl := NewControl (aDialog, ditlItemPtr^.displayRect,
- aString, TRUE, 0, 0, 0, pushButProc, 0);
-
- (* Put the control’s handle into our item list *)
- itemList^^ [itemNum].itemType := itemKind;
- itemList^^ [itemNum].itemControl := aControl;
-
- (* Bail if there’s not enough memory *)
- IF FailLowMemory (0) THEN
- RecoverError (memFullErr)
- ELSE IF aControl = NIL THEN
- IF (ResError = noErr) | (ResError = resNotFound) THEN
- RecoverError (resNotFound)
- ELSE
- RecoverError (ResError);
-
- (* Put the control’s item number into the control’s refCon *)
- SetCRefCon (aControl, itemNum)
- END
- ELSE IF itemKind = statText THEN
- BEGIN
- (* Allocate space for text *)
- staticText := NewHandleMargin (ditlItemPtr^.dataLen,
- kAllocApp, NOT kAllocClr);
-
- (* Put the control’s handle into our item list *)
- itemList^^ [itemNum].itemType := itemKind;
- itemList^^ [itemNum].itemText := staticText;
-
- (* Bail if there’s not enough memory for the text *)
- IF staticText = NIL THEN
- RecoverError (memFullErr);
-
- (* Copy DITL text to our text handle *)
- BlockMove (@ditlItemPtr^.itemText, staticText^, ditlItemPtr^.
- dataLen);
-
- (* Put a handle to the text into our item list *)
- aString [0] := CHR (0);
- IF ditlItemPtr^.pad0.fontIndex > 0 THEN
- BEGIN
- GetIndString ((*<*)aString, itemListNum, ditlItemPtr^.
- pad0.fontIndex);
- IF aString [0] = CHR (0) THEN
- GetIndString ((*<*)aString, 0, ditlItemPtr^.pad0.
- fontIndex)
- END;
- IF aString [0] = CHR (0) THEN
- fontNumber := 0
- ELSE
- GetFNum (aString, (*<*)fontNumber);
- itemList^^ [itemNum].itemTypeInfo.typeFace := fontNumber;
- itemList^^ [itemNum].itemTypeInfo.typeSize := ditlItemPtr^.
- pad0.statSize;
- itemList^^ [itemNum].itemTypeInfo.textJust := ditlItemPtr^.
- pad0.statJust;
- itemList^^ [itemNum].itemTypeInfo.typeStyle :=
- Style(ditlItemPtr^.pad0.statStyle)
- END
- ELSE
- itemList^^ [itemNum].itemType := itemKind;
-
- (* Copy interesting characteristics to our item list *)
- WITH itemList^^ [itemNum] DO
- BEGIN
- (*WITH*)displayRect := ditlItemPtr^.displayRect;
- (*WITH*)refCon := 0;
- (*WITH*)dismissor := doesDismiss
- END;
-
- (* Bump the pointer to the next item in the DITL *)
- dataLen := BAnd (ditlItemPtr^.dataLen + 1, $FFFE);
- ditlItemPtr := DITLTmplPtr(ORD4(@ditlItemPtr^.itemText) + dataLen)
- END;
-
- (* Don’t need the dialog item list any more *)
- HUnlock (ditlList);
- HPurge (ditlList);
- END;
-
-
- {$S DialogUtils}
- (*******************************************************************************
- * Public: SetStatTextItem
- *
- * The text of a static text item is specified by a handle to the text, so that
- * handle is resized to the new text length, if needed, and then the text is
- * simply BlockMoved in.
- *******************************************************************************)
-
- PROCEDURE SetStatTextItem (aDialog: DialogPtr;
- itemNum: Integer;
- textPtr: Ptr;
- textLength: Integer);
-
- VAR
- itemList: ItemListHnd; {Handle to item list}
- textHandle: Handle; {Handle to the existing item text}
-
- BEGIN
- (* Grab the item list from the dialog window’s refCon *)
- itemList := ItemListHnd(DialogPeek(aDialog)^.items);
-
- (* If the item is indeed a static text item, then set it *)
- IF itemList^^ [itemNum].itemType = statText THEN
- BEGIN
- textHandle := itemList^^ [itemNum].itemText;
- IF NOT FailLowMemory (textLength) THEN
- BEGIN
- IF GetHandleSize (textHandle) <> textLength THEN
- SetHandleSize (textHandle, textLength);
- BlockMove (textPtr, textHandle^, textLength)
- END
- END
- END;
-
-
- {$S DialogUtils}
- (*******************************************************************************
- * Public: GetStatTextFontInfo
- *
- * Font information for a static text item is simply stored in its itemTypeInfo
- * field. It’s a simple matter of copying this record into "typeInfo".
- *******************************************************************************)
-
- PROCEDURE GetStatTextFontInfo (aDialog: DialogPtr;
- itemNum: Integer;
- VAR typeInfo: TypeInfoRec);
-
- VAR
- itemList: ItemListHnd; {Handle to item list}
-
- BEGIN
- (* Grab the item list from the dialog window’s refCon *)
- itemList := ItemListHnd(DialogPeek(aDialog)^.items);
-
- (* If the item is indeed a static text item, then set it *)
- IF itemList^^ [itemNum].itemType = statText THEN
- typeInfo := itemList ^^ [itemNum].itemTypeInfo
- END;
-
-
- {$S DialogUtils}
- (*******************************************************************************
- * Public: DrawDialogItems
- *
- * The item list of a dialog box is stored in the "items" field of the
- * DialogRecord. This routine loops through every dialog item and draws whatever
- * item types it understands. Currently, this is static text items and icons.
- *******************************************************************************)
-
- PROCEDURE DrawDialogItems (aDialog: DialogPtr);
-
- VAR
- itemNum: Integer; {Item number of item we’re installing}
- itemList: ItemListHnd; {Handle to the item list}
- itemRect: Rect; {Rectangle of dialog item}
- staticText: Handle; {Handle to static text}
-
- BEGIN
- (* Draw any static text items or icon items in the item list*)
- itemList := ItemListHnd(DialogPeek(aDialog)^.items);
- itemNum := 0;
- WHILE itemList^^ [itemNum].itemType <> kNoItem DO
- BEGIN
- IF itemList^^ [itemNum].itemType = statText THEN
- BEGIN
- (* Item is a static text item; call TextBox if there’s text *)
- staticText := itemList^^ [itemNum].itemText;
- IF GetHandleSize (staticText) > 0 THEN
- BEGIN
- TextFont (itemList^^ [itemNum].itemTypeInfo.typeFace);
- TextSize (itemList^^ [itemNum].itemTypeInfo.typeSize);
- TextFace (itemList^^ [itemNum].itemTypeInfo.typeStyle);
- itemRect := itemList^^ [itemNum].displayRect;
- HLock (staticText);
- TextBox (staticText^, GetHandleSize (staticText),
- itemRect, itemList^^ [itemNum].itemTypeInfo.
- textJust);
- HUnlock (statictext)
- END
- END;
- itemNum := itemNum + 1
- END
- END;
-
-
- {$S DialogUtils}
- (*******************************************************************************
- * Public: GetDialogItemRect
- *
- * The item list of a dialog box is in the "items" field of the DialogRecord.
- * This handle is retrieved and the displayRect of the specified item into
- * "itemRect".
- *******************************************************************************)
-
- PROCEDURE GetDialogItemRect (aDialog: DialogPtr;
- itemNum: Integer;
- VAR itemRect: Rect);
-
- VAR
- itemList: ItemListHnd; {Handle to item list}
-
- BEGIN
- (* Grab the item list from the dialog window’s refCon *)
- itemList := ItemListHnd(DialogPeek(aDialog)^.items);
-
- (* Copy the item’s display rectangle *)
- itemRect := itemList^^ [itemNum].displayRect
- END;
-
-
- {$S DialogUtils}
- (*******************************************************************************
- * Public: DisposeDialogItems
- *
- * A handle to the dialog box’s dialog item list is retrieved from the
- * DialogRecord’s "items" handle. The type of each item is checked, and the
- * memory taken by that item is disposed of appropriately.
- *******************************************************************************)
-
- PROCEDURE DisposeDialogItems (aDialog: DialogPtr);
-
- VAR
- itemNum: Integer; {Item number of item we’re installing}
- itemList: ItemListHnd; {Handle to the item list}
-
- BEGIN
- (* Grab the item list from the dialog window’s refCon *)
- itemList := ItemListHnd(DialogPeek(aDialog)^.items);
-
- (* Starting at item 1, go through entire list and dispose of each item *)
- IF itemList <> NIL THEN
- BEGIN
- itemNum := 0;
- WHILE itemList^^ [itemNum].itemType <> kNoItem DO
- BEGIN
- WITH itemList^^ [itemNum] DO
- BEGIN
- IF (*WITH*)itemType = ctrlItem + btnCtrl THEN
- BEGIN
- IF (*WITH*)itemControl <> NIL THEN
- DisposeControl ((*WITH*)itemControl)
- END
- ELSE IF (*WITH*)itemType = statText THEN
- BEGIN
- IF (*WITH*)itemText <> NIL THEN
- DisposHandle ((*WITH*)itemText)
- END
- END;
-
- (* Go on to the next item in the item list *)
- itemNum := itemNum + 1
- END;
- DisposHandle (Handle(itemList))
- END
- END;
-